/*
 * FrontCodingEncoder_test.cpp
 *
 *  Created on: Nov 5, 2012
 *      Author: m
 */

#include "FrontCodingEncoder.h"

#include <memory>
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <sstream>

#define _ENCODE_MODE_ARG "-e"
#define _DECODE_MODE_ARG "-d"

typedef enum
{
    encode,
    decode,
    invalid
}
operation_mode_t;

std::string outfileName;
std::string infileName;
operation_mode_t mode;

void invalid_args()
{
    std::cerr << "Argumentos inválidos. "                                       << std::endl
            << "Uso: fc_ts [-e|-d] infile outfile"                              << std::endl
            << "Descripción: Codifica/Decodifica palabras usando front-coding." << std::endl
            << "Modos:"                                                         << std::endl
            << "\t-e: encode"                                                   << std::endl
            << "\t-d: decode"                                                   << std::endl;
    exit( 1 );
}

void parse_args( int argc, char* argv[] )
{
    if ( strcmp( argv[1], _ENCODE_MODE_ARG ) == 0 )
        mode = encode;
    else
        if ( strcmp( argv[1], _DECODE_MODE_ARG ) == 0 )
            mode = decode;
        else
            mode = invalid;

    infileName = argv[2];
    outfileName = argv[3];
}

int main( int argc, char* argv[] )
{
    std::ifstream infile;
    std::ofstream outfile;
    std::string lineBuffer;
    FrontCodingEncoder encoder;
    FrontCodingEncoder::FrontCodedString encodedString;
    std::stringstream ss;
    std::string decodedString;
    unsigned int aux;

    if ( argc < 4 )
        invalid_args();

    parse_args( argc, argv );

    infile.open( infileName );
    outfile.open( outfileName, std::ios_base::trunc );

    switch ( mode )
    {
    case encode:

        while( getline( infile , lineBuffer) )
        {
            encodedString = encoder.encode( lineBuffer );
            outfile << (unsigned int)encodedString.header << " " << encodedString.string << std::endl;
            encoder.setKey( lineBuffer );
        }
        break;

    case decode:

        while( getline( infile , lineBuffer) )
        {
            ss.str( lineBuffer );
            ss.clear();
            ss >> aux;
            ss >> encodedString.string;

            encodedString.header = aux;

            decodedString = encoder.decode( encodedString );

            outfile << decodedString << std::endl;
            encoder.setKey( decodedString );
        }
        break;

    case invalid:
        invalid_args();
        break;
    }

    infile.close();
    outfile.close();

    return 0;
}
